home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / BARNET / COMPILER / SATHER / !Sather / System / Common / h / exception < prev    next >
Text File  |  1997-01-14  |  5KB  |  148 lines

  1. /* 
  2.  * Copyright (C) International Computer Science Institute, 1994.  COPYRIGHT
  3.  * NOTICE: This code is provided "AS IS" WITHOUT ANY WARRANTY and is subject
  4.  * to the terms of the SATHER LIBRARY GENERAL PUBLIC LICENSE contained in
  5.  * the file "Doc/License" of the Sather distribution.  The license is also
  6.  * available from ICSI, 1947 Center St., Suite 600, Berkeley CA 94704, USA.
  7.  * ---> Please email comments to "sather-bugs@icsi.berkeley.edu". 
  8.  */
  9. #ifndef PSATHER 
  10.  
  11. #ifndef _EXC_SATHER_H_
  12. #define _EXC_SATHER_H_
  13.  
  14. #include <stddef.h>
  15. #include <stdlib.h>
  16. #if !defined (__riscos__)
  17. # include <sys/utsname.h>
  18. #endif
  19. #if defined(V_RISCOS) && defined(R_5_0) /* yoshida@agusa.nuie.nagoya-u.ac.jp */
  20. # ifndef SETJMP_H
  21. #  define SETJMP_H
  22. #  include <setjmp.h>
  23. # endif
  24. #else
  25. # include <setjmp.h>
  26. #endif
  27. #include <assert.h>
  28.  
  29. /*
  30.  * the structure EXCEPT_ELEMENT should not be used anywhere in the code
  31.  */
  32. struct EXCEPT_ELEMENT {
  33.         struct EXCEPT_ELEMENT *next;
  34.         jmp_buf jmp;
  35.         OB exception;
  36.     short mark;
  37. };
  38.  
  39. /*
  40.  * to use this code, you must define in ONE *.c file
  41.  * DEFINE_EXCEPTION_STACK outside any function to declare a global variable.
  42.  * or include this file in one *.c file after you've defined RUNTIME
  43.  */
  44. #define DEFINE_EXCEPTION_STACK static struct EXCEPT_ELEMENT exp_bottom;struct EXCEPT_ELEMENT *EXCEPTION_STACK=&exp_bottom
  45. #ifndef RUNTIME
  46. extern struct EXCEPT_ELEMENT *EXCEPTION_STACK;
  47. #else
  48. DEFINE_EXCEPTION_STACK;
  49. #endif
  50.  
  51. /*
  52.  * While executing a lock, try or protect statement, an exception stack
  53.  * is build. You can mark specific stack frames and unwind the stack to the
  54.  * first mark at any time. You have 16 different mark (0-15), but MARK(0)
  55.  * and MARK(1) are predefined. The first is used to mark the stack at the
  56.  * beginning of a function, while the second can be used for loops.
  57.  * Be warned however, that while ESCAPE unwinds the stack end ends the
  58.  * function, JUMP_OUT_OF_LOOP does NOT terminate the loop. You have to 
  59.  * manually end the loop by either a break or a goto.
  60.  */
  61. #define MARK(n)    (1<<(n))
  62. #define MARK_FUNCTION            MARK(0)
  63. #define MARK_LOOP            MARK(1)
  64. #define SET_EXCEPTION_MARK(n)        EXCEPTION_STACK->mark|=(n)
  65. #define REMOVE_EXCEPTION_MARK(n)    EXCEPTION_STACK->mark&= ~(n)
  66. #define POP_TO(m) do { while(EXCEPTION_STACK->mark&(m)==0) EXCEPTION_STACK=EXCEPTION_STACK->next; REMOVE_EXCEPTION_MARK(m) } while(0)
  67.  
  68. /*
  69.  * each function using ESCAPE MUST use EXCEPTION_PROLOGUE at the 
  70.  * beginning, and EXCEPTION_EPILOGUE at the end. Such a function may
  71.  * NOT use return.
  72.  */
  73. #define EXCEPTION_PROLOGUE     SET_EXCEPTION_MARK(MARK_FUNCTION);
  74. #define EXCEPTION_EPILOGUE     REMOVE_EXCEPTION_MARK(MARK_FUNCTION);
  75. #define ESCAPE            POP_TO(MARK_FUNCTION);return 
  76.  
  77. /*
  78.  * If you want to use mark on the stack to end loops, use
  79.  * LOOP_BEGIN before the loop and LOOP_END at its end.
  80.  * Note that JUMP_OUT_OF_LOOP must be followed by a break or goto,
  81.  * as it will not end the loop.
  82.  */
  83. #define LOOP_BEGIN        SET_EXCEPTION_MARK(MARK_LOOP);
  84. #define LOOP_END        REMOVE_EXCEPTION_MARK(MARK_LOOP);
  85. #define JUMP_OUT_OF_LOOP    POP_TO(MARK_LOOP)
  86.  
  87. /*
  88.  * To pop some frames from the exception stack, you may use POP_EXCEPTION.
  89.  * This macro can be used instead of LOOP_BEGIN and LOOP_END. The only
  90.  * problem is that you must know exactly how many frames to pop
  91.  * when exiting a loop.
  92.  */
  93. #define POP_EXCEPTION1  EXCEPTION_STACK=EXCEPTION_STACK->next
  94. #define POP_EXCEPTION(n) do { int i=n;while(i-->0) POP_EXCEPTION1; } while(0)
  95.  
  96. /*
  97.  * RAISE(x) raises an exception. The value x (actually a pointer) is passed
  98.  * to the exception handling routine, which can use it through the
  99.  * macro EXCEPTION. If this routine needs to propagate the exception,
  100.  * it can use RAISE(EXCEPTION)
  101.  */
  102. #define UNCAUGHT_EXCEPTION 0
  103. /* This macro is somewhat tricky since ex could be instantiated with EXCEPTION
  104.  * when propagating the exception to the handler above. If so, 
  105.  * EXCEPTION is expanded into EXCEPTION_STACK->exception, but EXCEPTION_STACK
  106.  * is changed in the macro and a horrible name capture happens. To avoid it,
  107.  * we need to copy "ex" into local "the_ex" immediately and use "the_ex"
  108.  * everywhere.
  109.  * Fixed on 8/23/96
  110.  * Boris
  111.  */
  112.  
  113. #define RAISE(ex) do { OB the_ex = ex;                                  \
  114.         struct EXCEPT_ELEMENT *PREV_EXCEPTION_STACK=EXCEPTION_STACK;    \
  115.                        EXCEPTION_STACK=PREV_EXCEPTION_STACK->next;         \
  116.                if(PREV_EXCEPTION_STACK->next!=NULL) {        \
  117.                    EXCEPTION_STACK->exception=the_ex;          \
  118.                    longjmp(PREV_EXCEPTION_STACK->jmp,1);     \
  119.                } else assert(UNCAUGHT_EXCEPTION);        \
  120.               } while(0)
  121. #define EXCEPTION                ((OB)EXCEPTION_STACK->exception)
  122.  
  123. /* 
  124.  * To protect some statements A against exception, use
  125.  * PROTECT_BEGIN
  126.  *    A;
  127.  * PRTOECT_WHEN
  128.  *    if(EXCEPTION==....
  129.  * PRTOECT_END
  130.  * If PROTECT_END is ever executed because the exception handler does
  131.  * neither end the program, nor raise another exceptioexception or ESCAPE 
  132.  * (see above), the exception is automatically propagated back to the 
  133.  * next PROTECT by a RAISE(EXCEPTION).
  134.  */
  135. #define PROTECT_BEGIN       { struct EXCEPT_ELEMENT p_n;              \
  136.                  if(setjmp(p_n.jmp)==0) {                   \
  137.                 p_n.next=EXCEPTION_STACK;             \
  138.                 p_n.mark=0;                     \
  139.                 EXCEPTION_STACK= &p_n;
  140.              
  141. #define PROTECT_WHEN         POP_EXCEPTION1; } else {
  142. #define PROTECT_END         }                            \
  143.                }
  144.  
  145. #endif
  146.  
  147. #endif
  148.